﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Threading;
using System.Xml.Serialization;
using System.Diagnostics;
using WMPLib;

using MusicPlayerLib.DataModel;

namespace MusicPlayerLib.Utils
{
    public class MusicPlayerUtils
    {
        private static string[] supportedFileType ={
                ".mp3",".wma",".wav"};
        private static WindowsMediaPlayer wmp;


        public static WindowsMediaPlayer GetWmpInstance()
        {
            if (wmp == null)
            {
                wmp = new WindowsMediaPlayer();
                wmp.settings.autoStart = false;
            }
            return wmp;
        }
        
        
        /// <summary>
        /// 根据专辑名和歌手名称生成唯一的专辑ID
        /// </summary>
        /// <param name="title"></param>
        /// <param name="artist"></param>
        /// <returns></returns>
        public static string GetAlbumId(string title, string artist)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] bytes=System.Text.Encoding.UTF8.GetBytes((title + "." + artist).ToUpper());
            byte[] result = md5.ComputeHash(bytes);

            bytes = md5.ComputeHash(bytes); 
            md5.Clear(); 

            string ret = ""; 
            for (int i = 0; i < bytes.Length; i++) 
            { 
                ret += Convert.ToString(bytes[i], 16).PadLeft(2, '0'); 
            } 

            return ret.PadLeft(32, '0'); 
          }

        /// <summary>
        /// 从指定的文件夹中读取音频文件，生成MediaLibrary类;
        /// </summary>
        /// <param name="dirs"></param>
        /// <returns></returns>
        public static MediaLibrary GenerateMediaLibrary(DirectoryInfo[] dirs)
        {
            //支持的文件类型;
            List<string> supportedFileType = new List<string>();
            supportedFileType.Add(".wma");
            supportedFileType.Add(".wav");
            supportedFileType.Add(".mp3");

           MediaLibrary mediaLibrary=new MediaLibrary();

            foreach (DirectoryInfo dir in dirs)
            {
                try
                {
                    //所有子文件;
                    FileInfo[] files = dir.GetFiles();
                    //所有子文件夹
                    DirectoryInfo[] subDirs = dir.GetDirectories();

                    if (files.Length > 0)
                    {
                        foreach (FileInfo f in files)
                        {
                            if (supportedFileType.Contains(f.Extension))
                            {
                                //根据该文件获得音频文件的信息，并且添加至MeidaLibrary；
                                AudioFile af = new AudioFile(f.FullName);
                                mediaLibrary.Tracks.Add(af);

                                Console.WriteLine("Processing {0}", af.Location);

                                //生成该曲目的专辑类
                                Album album = new Album(af.Album, af.Artist, af.Genre, af.Year, 0);
                                int index = mediaLibrary.Albums.IndexOf(album);
                                if (index < 0)
                                {
                                    string coverLocation = CoverArtUtils.SaveCover(af);
                                    album.CoverLocation = coverLocation;

                                    mediaLibrary.Albums.Add(album);
                                }
                                else
                                {
                                    Album target = mediaLibrary.Albums[index];
                                    target.TrackNum += 1;
                                    //如果专辑还没有封面则尝试从该文件中读取封面;
                                    string coverLocation = CoverArtUtils.SaveCover(af);
                                    if (target.CoverLocation.Equals(string.Empty) &&
                                        coverLocation.Equals(string.Empty))
                                        target.CoverLocation = coverLocation;
                                }

                                Artist artist = new Artist(af.Artist);
                                if (!(mediaLibrary.Artists.Contains(artist)))
                                    mediaLibrary.Artists.Add(artist);
                            }
                        }
                    }

                    //遍历子文件夹
                    if (subDirs.Length > 0)
                    {
                        MediaLibrary ml = MusicPlayerUtils.GenerateMediaLibrary(subDirs);
                        //将找到的AudioFile加入到MediaLibrary中;
                        mediaLibrary.Tracks.AddRange(ml.Tracks);

                        //判断找到的Album和Artist是否已经包括在内，是则跳过，否则加入
                        foreach (Album album in ml.Albums)
                        {
                            int index = -1;
                            if ((index = mediaLibrary.Albums.IndexOf(album)) >= 0)
                            {

                                mediaLibrary.Albums[index].TrackNum += 1;
                            }
                            else
                            {
                                mediaLibrary.Albums.Add(album);
                            }
                        }

                        foreach (Artist artist in ml.Artists)
                        {
                            if (!mediaLibrary.Artists.Contains(artist))
                            {
                                mediaLibrary.Artists.Add(artist);
                            }
                        }

                    }
                }
                catch(Exception e)
                {
                    Debug.WriteLine(e.StackTrace);
                }
            }
            return mediaLibrary;
        }

        /// <summary>
        /// 根据歌手的名称获得歌手ID
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string GetArtistId(string name)
        {
            return name.ToUpper().GetHashCode() + "";
        }

        /// <summary>
        /// 获得给定的音乐文件的时长;
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static double GetAudioDuration(string path)
        {
            WindowsMediaPlayer player = MusicPlayerUtils.GetWmpInstance();
            try
            {
                player.URL = path;
                int time = 0;
                player.controls.play();
                double duration=player.currentMedia.duration;
                while (duration==0&&time < 30)
                {
                    Thread.Sleep(200);
                    duration = player.currentMedia.duration;
                    time++;
                }
                player.controls.stop();
                return duration;
            }
            catch (Exception e)
            {
                return 0;
            }
        }


        /// <summary>
        /// 获得指定文件夹下的所有支持的文件;
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static List<AudioFile> GetAudioFiles(DirectoryInfo d)
        {
            List<AudioFile> afs=new List<AudioFile>();

            //Get Files;
            FileInfo[] files = d.GetFiles();
            foreach(FileInfo f in files)
            {
                if (IsSupported(f))
                {
                    afs.Add(new AudioFile(f.FullName));
                }
            }

            //Get Directories;
            DirectoryInfo[] dirs = d.GetDirectories();
            foreach (DirectoryInfo dir in dirs)
            {
                List<AudioFile> part = GetAudioFiles(dir);
                afs.AddRange(part);
            }

            return afs;
        }

        private static bool IsSupported(FileInfo f)
        {
            foreach (string s in supportedFileType)
            {
                if (f.Extension.Equals(s))
                    return true;
            }
            return false;
        }

        public static MediaLibrary LoadMediaLibrary(string path)
        {
            try
            {
                FileStream fs = new FileStream(path, FileMode.Open);

                XmlSerializer xs = new XmlSerializer(typeof(MediaLibrary));
                MediaLibrary ml = (MediaLibrary)xs.Deserialize(fs);

                return ml;
            }
            catch (Exception e)
            {
                return null;
            }
        }

        public static void SaveMediaLibary(string path,MediaLibrary ml)
        {
            FileInfo file = new FileInfo(path);
            if (file.Exists)
            {
                file.Delete();
            }
            XmlSerializer xs = new XmlSerializer(typeof(MediaLibrary));
            FileStream fs = new FileStream(path, FileMode.CreateNew);
            xs.Serialize(fs, ml);
        }
    }
}
